`define IDEL 2'b00
`define IF_R 2'b01
`define LS_R 2'b10
module MODULE_AXI_Arbiter
#(AWIDTH = 32,
	DWIDTH = 64,
	MASKLEN = 8
)
(
	input								clk_i,
	input								rst_i,
	//AXI4_Lite IFU
	input	[AWIDTH-1:0]	araddr_F_i,
	input								arvalid_F_i,
	output									arready_F_o,//

	output		[DWIDTH-1:0]	rdata_F_o,
	output		[1:0]					rresp_F_o,//
	output									rvalid_F_o,//
	input								rready_F_i,
	input			[2:0]				arsize_F_i,
	//AXI4_Lite LSU
	input	[AWIDTH-1:0]	araddr_LS_i,
	input								arvalid_LS_i,
	output									arready_LS_o,//

	output		[DWIDTH-1:0]	rdata_LS_o,
	output		[1:0]					rresp_LS_o,//
	output									rvalid_LS_o,//
	input								rready_LS_i,
	
	input	[AWIDTH-1:0]	awaddr_LS_i,
	input								awvalid_LS_i,
	output									awready_LS_o,

	input	[DWIDTH-1:0]	wdata_LS_i,
	input	[MASKLEN-1:0]	wstrb_LS_i,
	input								wvalid_LS_i,
	output									wready_LS_o,

	output		[1:0]					bresp_LS_o,//not finished 
	output									bvalid_LS_o,//not...
	input								bready_LS_i,//not...
	input								 wlast_LS_i,
	input			[2:0]			 arsize_LS_i,
	input			[2:0]			 awsize_LS_i,
	//AXI_Lite MEM
	output	[AWIDTH-1:0]	araddr_o,
	output								arvalid_o,
	input									arready_i,//

	input		[DWIDTH-1:0]	rdata_i,
	input		[1:0]					rresp_i,//
	input									rvalid_i,//
	output								rready_o,
	
	output	[AWIDTH-1:0]	awaddr_o,
	output								awvalid_o,
	input									awready_i,

	output	[DWIDTH-1:0]	wdata_o,
	output	[MASKLEN-1:0]	wstrb_o,
	output								wvalid_o,
	input									wready_i,

	input		[1:0]					bresp_i,//not finished 
	input									bvalid_i,//not...
	output								bready_o,//not..
	
	output								wlast_o,
	output  [2:0]					arsize_o,
	output  [2:0]					awsize_o
);
//LSU_write
assign awaddr_o = awaddr_LS_i;
assign awvalid_o = awvalid_LS_i;
assign awready_LS_o= awready_i ;
assign wdata_o = wdata_LS_i;
assign wstrb_o = wstrb_LS_i;
assign wvalid_o = wvalid_LS_i;
assign wready_LS_o= wready_i ;
assign bresp_LS_o= bresp_i ;
assign bvalid_LS_o= bvalid_i ;
assign bready_o = bready_LS_i;
assign awsize_o = awsize_LS_i;
assign wlast_o = wlast_LS_i;
//read IFU always before the LSU
wire [1:0]	state_now;
wire [1:0]  state_next;
Reg #(2,0) state_now_reg(clk_i,rst_i,state_next[1:0],state_now[1:0],1);
MuxKeyWithDefault #(3,2,2) state_next_mux(.out(state_next[1:0]),.key(state_now[1:0]),.default_out(0),.lut({
	`IDEL	,arvalid_F_i?`IF_R:arvalid_LS_i?`LS_R:`IDEL,
	`IF_R	,rvalid_F_o ?`IDEL:`IF_R,
	`LS_R	,rvalid_LS_o ? `IDEL:`LS_R
}));

assign arready_F_o = (state_now[1:0] == `IF_R) ? arready_i:0;
assign arready_LS_o = (state_now[1:0] == `LS_R) ? arready_i:0;
assign rdata_F_o[DWIDTH-1:0] = rdata_i[DWIDTH-1:0];
assign rdata_LS_o[DWIDTH-1:0] = rdata_i[DWIDTH-1:0];
assign rresp_F_o[1:0] = rresp_i[1:0];
assign rresp_LS_o[1:0] =rresp_i[1:0];
assign rvalid_F_o	=  (state_now[1:0] == `IF_R) ? rvalid_i:0;
assign rvalid_LS_o	=  (state_now[1:0] == `LS_R) ? rvalid_i:0;
MuxKeyWithDefault #(3,2,AWIDTH) araddr_mux(.out(araddr_o[AWIDTH-1:0]),.key(state_now[1:0]),.default_out(0),.lut({
	`IDEL	,{AWIDTH{1'b0}},
	`IF_R	,araddr_F_i[AWIDTH-1:0],
	`LS_R	,araddr_LS_i[AWIDTH-1:0]
}));
MuxKeyWithDefault #(3,2,1) arvalid_mux(.out(arvalid_o),.key(state_now[1:0]),.default_out(0),.lut({
	`IDEL	,1'b0,
	`IF_R	,arvalid_F_i,
	`LS_R	,arvalid_LS_i
}));
MuxKeyWithDefault #(3,2,1) rready_next_mux(.out(rready_o),.key(state_now[1:0]),.default_out(0),.lut({
	`IDEL	, 1'b0,
	`IF_R	, rready_F_i,
	`LS_R	, rready_LS_i
}));
MuxKeyWithDefault #(3,2,3) arsize_mux(.out(arsize_o[2:0]),.key(state_now[1:0]),.default_out(0),.lut({
	`IDEL	, 3'b0,
	`IF_R	, arsize_F_i[2:0],
	`LS_R	, arsize_LS_i[2:0] 
}));
endmodule
